﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using UtilZ.Dotnet.Ex.Base;

namespace UtilZ.Dotnet.Ex.DataStruct
{
    /// <summary>
    /// 定时任务
    /// </summary>
    public class TimingTask : ITimingTask
    {
        /// <summary>
        /// 回调
        /// </summary>
        private readonly Action<TimingTask> _callback;

        /// <summary>
        /// 任务名称
        /// </summary>
        public string Name { get; set; } = "匿名定时任务";

        /// <summary>
        /// 执行间隔毫秒数
        /// </summary>
        private readonly int _intervalMilliseconds;
        /// <summary>
        /// 执行间隔毫秒数
        /// </summary>
        public int IntervalMilliseconds
        {
            get { return _intervalMilliseconds; }
        }

        /// <summary>
        /// 执行次数,小于0表示无限,大于等于0表示执行指定次数
        /// </summary>
        private readonly int _count;
        /// <summary>
        /// 执行次数,小于0表示无限,大于等于0表示执行指定次数
        /// </summary>
        public int Count
        {
            get { return _count; }
        }

        /// <summary>
        /// 获取或设置与缓存数据关联的用户定义的数据
        /// </summary>
        public object Tag { get; set; }




        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="callback">回调</param>
        /// <param name="intervalMilliseconds">执行间隔毫秒数</param>
        /// <param name="count">执行次数,小于0表示无限,大于等于0表示执行指定次数</param>
        public TimingTask(Action<TimingTask> callback, int intervalMilliseconds, int count = -1)
        {
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            this._callback = callback;
            this._intervalMilliseconds = intervalMilliseconds;
            this._count = count;
        }


        /// <summary>
        /// 当前任务已执行次数
        /// </summary>
        private int _excuteCount = 0;


        /// <summary>
        /// 查检定时任务是否已经执行完成[返回true:执行完成;false:未执行完成]
        /// </summary>
        /// <returns>true:执行完成;false:未执行完成</returns>
        public bool IsDone()
        {
            if (this._count < 0)
            {
                return false;
            }

            return this._excuteCount >= this._count;
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        public void Excute()
        {
            this._callback(this);

            if (this._count >= 0)
            {
                this._excuteCount++;
            }
        }

        private long _nextExcuteTimestamp = -1L;
        /// <summary>
        /// 判断当前任务是否需要执行[true:需要执行;false:不需要执行]
        /// </summary>
        /// <returns>true:需要执行;false:不需要执行</returns>
        public bool HasExcute()
        {
            if (this._nextExcuteTimestamp < 0)
            {
                return true;
            }

            long timestamp = TimeEx.GetTimestamp();
            if (timestamp >= this._nextExcuteTimestamp)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 获取下次执行需要等待的时长,单位:毫秒
        /// </summary>
        /// <param name="timestamp">当前时间戳</param>
        /// <returns>当前任务到下一次执行的还需要的延迟时间</returns>
        public long GetNextExcuteWaitMilliseconds(long timestamp)
        {
            if (this._nextExcuteTimestamp < 0)
            {
                return 0L;
            }

            if (this._nextExcuteTimestamp <= timestamp)
            {
                return 0L;
            }
            else
            {
                return this._nextExcuteTimestamp - timestamp;
            }
        }

        /// <summary>
        /// 更新任务执行完成时间戳
        /// </summary>
        public void UpdateExcuteTimestamp()
        {
            this._nextExcuteTimestamp = TimeEx.GetTimestamp() + this._intervalMilliseconds;
        }


        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {

        }
    }

}
